package jpave.qr;

/****************************************
 * Graphical interface for computing DE (runDE)
 */
import java.awt.Color;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.net.InetAddress;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.TreeSet;
import java.util.Vector;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.WindowConstants;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

import assem.Utils;
import jpave.manager.ManagerFrame;
import jpave.query_interface.JPaveMain;

//import cmp.compile.panels.CompilePanel;

import util.Debug.ErrorReport;
import util.methods.ArrayHelpers;
import util.methods.HostsCfg;
import util.methods.UIHelpers;
import util.ui.ButtonComboBox;
import util.ui.UserPrompt;
import jpave.database.JPaveDBWrapper;
import jpave.database.OverviewDBWrapper;
import jpave.dataholders.AssemblyData;
import jpave.dataholders.DatabaseData;
import jpave.dataholders.GlobalSettings;
import jpave.dataholders.SessionData;


public class QRFrame extends JDialog implements WindowListener {
	private static final long serialVersionUID = 6227242983434722745L;

	private static final String [] SELECTIONS = { "Libraries", "Group 1", "Group 2", "Exclude" };
	private static final int DEFAULT_SELECTION = 2; 
	private static final int COLUMN_WIDTH = 140;
	private static final String pValColPrefix = "P_";
	private static final String defPercent = "10";
	private static final String defPVal = ".05";
	public static final String allCols = "All Pval Columns";
	public static final String selCol = "Select Pval Column";
	private static final String BADCOLNAME = "Invalid column name, use up to 15 letters/numbers/underscores";

	private static Vector<QRFrame> openWindows = null;
	private static HostsCfg hosts;
	
	/** opens window with list of TCW dbs **/
	public QRFrame() 
	{
		hosts = new HostsCfg();
		paveDBs = new GlobalSettings();
		paveDBs.loadFromHosts();
		initChooser();

	}
	public QRFrame(GlobalSettings dbs) 
	{		
		paveDBs = dbs;
		initChooser();
	}	
	private void initChooser() // assuming paveDBs has been set
	{
		openWindows = new Vector<QRFrame> ();
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		JPanel selectPanel = 
				createAssemblySelectionPanel(getSettings().getAllSessions());
		try {
			setTitle("runDE on " + InetAddress.getLocalHost().getHostName());
		}
		catch (Exception e){ setTitle("runDE");}
		
		setResizable(true);
		add(selectPanel);
		setWindowSettings("deframechooser");
		setVisible(true);		
	}
	private void setWindowSettings(final String prefix) {
		UIHelpers.centerScreen(this);
		pack();
	}

	/** open window for a PAVEdb with its libraries **/
	public QRFrame(GlobalSettings dbs, String options)  throws Exception
	{
		hosts = new HostsCfg();
		parent = this;
		paveDBs = dbs; 
		// if window is launched from viewSingleTCW, this has not been initialized
		if(openWindows == null)
			openWindows = new Vector<QRFrame> ();
		openWindows.add(this);
		addWindowListener(this);
		setConnection(options);
		qrProcess = new QRProcess(selectedDB, conn);
		
		setTitle("runDE " + JPaveMain.JPAVE_VERSION + ": " + strTitle);
		createRowHeaders(theLibraryNames);
		createMainPanel();
		createSelections();
		mainPanel.add(new JSeparator());
		mainPanel.add(Box.createVerticalStrut(10));
		mainPanel.add(getModePanel());

		mainPanel.add(Box.createVerticalStrut(10));
		mainPanel.add(createNormPanel());

		mainPanel.add(Box.createVerticalStrut(10));
		mainPanel.add(createDispPanel());

		mainPanel.add(Box.createVerticalStrut(10));
		mainPanel.add(createFDRPanel());

		mainPanel.add(Box.createVerticalStrut(10));
		mainPanel.add(createDBPanel());
		
		mainPanel.add(Box.createVerticalStrut(10));
		mainPanel.add(Box.createVerticalStrut(10));
		mainPanel.add(createExecutePanel());
		
		mainPanel.add(Box.createVerticalStrut(10));
		mainPanel.add(new JSeparator());
		mainPanel.add(Box.createVerticalStrut(10));
		mainPanel.add(createRemovePanel());
		mainPanel.add(Box.createVerticalStrut(10));
		mainPanel.add(createGOPanel());
		updateColumnList();
		setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
	
		mainPanel.setMaximumSize(mainPanel.getPreferredSize());
		mainPanel.setMinimumSize(mainPanel.getPreferredSize());
		
		setResizable(true);
		add(mainPanel);
		setWindowSettings("QRframemainview");
		setVisible(true);
	}
	/********************************************************
	 * XXX doExecute -- calls QRprocess.doExecute
	 * 		gathers and checks all parameters
	 */
	private void doExecute(int modeID, int normID, int minorID, String colName, double disp){
		// user selected groups
		TreeSet<String> grp1 = new TreeSet <String> ();
		TreeSet<String> grp2 = new TreeSet <String> ();		
		for(int x=0; x<theLibraryNames.length; x++) 
		{
			if (isSelectedAt(x, 0))
				grp1.add(theLibraryNames[x]);
			else if (isSelectedAt(x, 1))
				grp2.add(theLibraryNames[x]);
		}
		if (grp1.size() == 0 || grp2.size() == 0)
		{
			JOptionPane.showMessageDialog(null,"Empty group! Please select at least one library for each group.");
			return;
		}
		boolean addCol = true;
		if (!btnAddCol.isSelected()) addCol=false;
		else {
			if (!colNameOK(colName, 1)) return; 
			if (!colNameUnique(colName, 1)) return;
		}

		if (addCol) 
			System.err.println("\nStart DE execution - add results to column " + colName);
		else
			System.err.println("\nStart DE execution - results not added to database");
	
		String pColName = pValColPrefix + colName;
		boolean doFDR = btnFDR.isSelected();
		qrProcess.doExecute(modeID, normID, minorID, pColName, addCol, doFDR, grp1, grp2, disp);
	}

	private void doExecuteAll(int modeID, int normID, int minorID, double disp){
		
		TreeSet<String> grp1 = new TreeSet <String> ();
		TreeSet<String> grp2 = new TreeSet <String> ();	
		
		Vector<String> libNames = new Vector<String>();
		for(int x=0; x<theLibraryNames.length; x++) 
		{
			if (isSelectedAt(x, 0))
				libNames.add(theLibraryNames[x]);
		}
		String libs = Utils.strVectorJoin(libNames, ",");
		String msg = "Do all pairs for:" + libs + "\n and save to auto-named columns";	
		int ret = JOptionPane.showOptionDialog(null, msg,
				"runDE", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null);
		if (ret != JOptionPane.YES_OPTION)
		{
			System.err.println("Abort Execute");
			return;
		}
		btnAddCol.setSelected(true);
		
		for(int x=0; x<libNames.size(); x++) 
		{
			grp1.clear();
			String lib1 = libNames.get(x);
			grp1.add(lib1);
			for(int x2=x+1; x2<libNames.size(); x2++) 
			{
				grp2.clear();
				String lib2 = libNames.get(x2);
				grp2.add(lib2);
				
				boolean addCol = true;			
				String pColName = colNameCreate(lib1,lib2);
		
				System.err.println("****************************************************************");
				System.err.println("******** Start DE execution for column: " + pColName + " *********");
				System.err.println("****************************************************************");
				
				pColName = pValColPrefix + pColName;
				boolean doFDR = btnFDR.isSelected();
				qrProcess.doExecute(modeID, normID, minorID, pColName, addCol, doFDR, grp1, grp2, disp);
			}
		}
		System.err.println("Complete all pairs");
	}
	// XXX read file of group1, group2, columnname
	private void doExecuteFile(int modeID, int normID, int minorID, double disp, String fname){
		try {
			System.err.println("\nReading " + fname);
			
			Vector <String> addLines = new Vector <String> ();
			
			btnAddCol.setSelected(true);
			BufferedReader file = new BufferedReader(new FileReader(fname));
			String line, colSaveStr="", pColName;
			
			// read file and check
			TreeSet<String> libs = new TreeSet <String> ();
			int cnt=0, err=0, warn=0;
			while((line = file.readLine()) != null) {
				line = line.trim();
				if (line.equals("")) continue;
				if (line.startsWith("#")) continue;
				
				libs.clear();
				boolean good=true;
				System.err.println("Input: " + line);
				
				String [] col = line.split("\\s+");
				if (col.length != 3) {
					System.err.println("   -- ignore, improper line ");
					err++; good=false;
					continue;
				}
				
				// columns can be multiple groups delimited by :
				if (col[0].contains(":")) {
					String [] set = col[0].split(":");
					for (int i=0; i< set.length; i++) {
						libs.add(set[i]);
					}
				}
				else libs.add(col[0]); 
				
				if (col[1].contains(":")) {
					String [] set = col[1].split(":");
					for (int i=0; i< set.length; i++) {
						libs.add(set[i]);
					}
				}
				else libs.add(col[1]); 
				
				// libraries exist?
				for (String lib : libs) {
					boolean found=false;
					for(int x=0; x<theLibraryNames.length && !found; x++) 
						if (lib.equals(theLibraryNames[x])) found = true;
					if (!found) {
						System.err.println("   " + lib + " -- ignore, library not found");
						err++; good=false;
					}
				}
				
				// check for proper name and uniqueness
				if (!colNameOK(col[2], 2)) {
					err++; good=false;
				}
				else if (colSaveStr.contains(" " + col[2] + " ")) {
					System.err.println("  " + col[2] + "  -- ignore, duplicate column");
					err++; good=false;
				}
				else if (!colNameUnique(col[2], 2)) {
					warn++; 
				}
				
				if (good) {
					colSaveStr += " " + col[2] + " ";
					addLines.add(line);
					cnt++;
				}
			}
			// prompt the user
			String msg = "Found " + cnt + " good entries";
			if (warn>0) msg += " with " + warn + " overwrite (see terminal)";
			if (err>0) msg += " and " + err + " ignored entries (see terminal)";

			int ret = JOptionPane.showOptionDialog(null, msg,
					"runDE", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null);
		
			if (ret != JOptionPane.YES_OPTION)
			{
				System.err.println("Abort Execute");
				return;
			}
			
			// read and compute
			TreeSet<String> grp1 = new TreeSet <String> ();
			TreeSet<String> grp2 = new TreeSet <String> ();
			
			for (int j=0; j<addLines.size(); j++) {
				line = addLines.get(j);
				String [] col = line.split("\\s+");
				grp1.clear(); grp2.clear();
				if (col[0].contains(":")) {
					String [] set = col[0].split(":");
					for (int i=0; i< set.length; i++) grp1.add(set[i]);
				}
				else grp1.add(col[0]); 
				
				if (col[1].contains(":")) {
					String [] set = col[1].split(":");
					for (int i=0; i< set.length; i++) grp2.add(set[i]);
				}
				else grp2.add(col[1]); 
				
				pColName = pValColPrefix + col[2];
			
				System.err.println("****************************************************************");
				System.err.println("******** Start DE execution for column: " + col[2] + " *********");
				System.err.println("****************************************************************");
				
				boolean doFDR = btnFDR.isSelected();
				qrProcess.doExecute(modeID, normID, minorID, pColName, true, doFDR, grp1, grp2, disp);
			}
			System.err.println("Complete adding from file");
		}
		catch (Exception e) {
			ErrorReport.reportError(e, "Cannot process file " + fname);
		}
	}
	/********************************************************
	 * XXX Creates a default column name for the libraries selected
	 * It tries to 'guess' what kind of naming scheme these are using
	 */
	private String colNameCreate(TreeSet<String> grp1, TreeSet<String> grp2, String colName) {
		String col="";
		String a="", b="";
		if (grp1.size() ==1 && grp2.size() == 1) {
			boolean isLt4 = true;
			
			for(int x=0; x<theLibraryNames.length; x++) // tries to keep them all the same length
				if (theLibraryNames[x].length() > 3) isLt4 = false;
			
			for(int x=0; x<theLibraryNames.length; x++) 
			{
				if (isSelectedAt(x, 0)) a = theLibraryNames[x];
				else if (isSelectedAt(x, 1)) b = theLibraryNames[x];
			}
			
			if (isLt4)  col = a + b;
			else {
				String aa =  (a.length()>=2) ? a.substring(0,2) : a; 
				String bb =  (b.length()>=2) ? b.substring(0,2) : b; 
				if (!aa.equals(bb) && (aa.length() + bb.length() < 6)) col = aa+bb;			
				else if (a.length() + b.length() < 6) col =  a + b;
				else {
					String aaa =  (aa.length()>=3) ? aa.substring(0,3) : aa; 
					String bbb =  (bb.length()>=3) ? bb.substring(0,3) : bb; 
					col = aaa+bbb;
				}
			}
		}
		else {
			for(int x=0; x<theLibraryNames.length; x++) 
			{
				if (isSelectedAt(x, 0)) a += theLibraryNames[x].charAt(0);
				else if (isSelectedAt(x, 1)) b += theLibraryNames[x].charAt(0);
			}
			col =   a + "x" + b; // can't use '_" because of L_ and LN_ columns in sTCW
		}
		if (!colNameOK(col, 2)) {
			if (colNameOK(col+"2", 2)) col += "2";
			else if (colNameOK(col+"3", 2)) col += "3";
			else return "";
		}
		return col;
	}
	// For the looping mode, since it can't use the interface selection
	private String colNameCreate(String a, String b) {
		String col="";
		boolean isLt4 = (a.length() < 4 && b.length() < 4);
		
		if (isLt4)  col = a + b;
		else {
			String aa =  (a.length()>=2) ? a.substring(0,2) : a; 
			String bb =  (b.length()>=2) ? b.substring(0,2) : b; 
			if (!aa.equals(bb) && (aa.length() + bb.length() < 6)) col = aa+bb;
			else if (a.length() + b.length() < 6) col = a + b;
			else {
				String aaa =  (aa.length()>=3) ? aa.substring(0,3) : aa; 
				String bbb =  (bb.length()>=3) ? bb.substring(0,3) : bb; 
				col = aaa+bbb;
			}
		}
		if (!colNameOK(col, 2)) {
			if (colNameOK(col+"2", 2)) col += "2";
			else if (colNameOK(col+"3", 2)) col += "3";
			else return "";
		}
		return col;
	}
	/************************************************************
	 * Column checking
	 * L__ cannot have the same name as the table crashes
	 */
	private boolean colNameOK(String colName, int msg) {// msg=0 none, 1 dialog, 2 stderr
		try {
			if (colName.length() <= 0) {
				if (msg==1) JOptionPane.showMessageDialog(null, "No column name");
				else if (msg==2) 
					System.err.println("   " + colName + " -- ignore, no column name");
				return false;
			}
			
			if (colName.length() > 15 || !colName.matches("[\\w]+"))
			{
				if (msg==1) JOptionPane.showMessageDialog(null, colName + " " + BADCOLNAME);
				else if (msg==2) 
					System.err.println("   " + colName + " -- ignore, " + BADCOLNAME);			
				return false;
			}
		 
			String [] L_Col = JPaveDBWrapper.getPrefixedColumns(conn, "L__");
			for (int i=0; i<L_Col.length; i++) {
				if (L_Col[i].equals(colName)) {
					if (msg==1)
						JOptionPane.showMessageDialog(null,"Invalid: " + colName + " exists as library name");
					else if (msg==2) 
						System.err.println("   " + colName + " -- ignore, exists as library name");
					return false;				
				}
			}
			return true;
		}
		catch (Exception e) {
			ErrorReport.reportError("checking column" + colName, e);
			return false;
		}
	}

	private boolean colNameUnique(String colName, int msg) {
		try { 
			String [] P_Col = JPaveDBWrapper.getPrefixedColumns(conn, "P_");
		
			for (int i=0; i<P_Col.length; i++) {
				if (P_Col[i].equals(colName)) {			
					if (msg==1) {
						int ret = JOptionPane.showConfirmDialog(null, "Name " + colName + 
								" was already used. Do you want to overwrite the previous scores?\n" +
								"(see Help about generating column names)");	
						if (ret != JOptionPane.YES_OPTION)
						{
							System.err.println("Abort Execute");
							return false;
						}
					}
					else if (msg==2)  {
						System.err.println("   " + colName + " -- overwrite, exists in database ");
						return false; 
					}
					return true;
				}
			}
			return true;
		}
		catch (Exception e) {
			ErrorReport.reportError("checking column exists" + colName, e);
			return false;
		}
	}
	/******************************************************
	 * QR panel methods
	 */
	private void createMainPanel() {
		mainPanel = new JPanel();
		mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.PAGE_AXIS));
		mainPanel.setBackground(Color.WHITE);
		
		mainPanel.add(createColumnHeaders());
		mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
	}
	
	private JPanel createColumnHeaders() {
		JPanel row = getRowPanel();

		colHeaders = new JLabel[SELECTIONS.length];
		for(int x=0; x<SELECTIONS.length; x++) {
			colHeaders[x] = new JLabel(SELECTIONS[x]);
			colHeaders[x].setAlignmentX(Component.CENTER_ALIGNMENT);
			
			JPanel temp = getRowPanel();
			temp.add(colHeaders[x]);
			Dimension d = temp.getPreferredSize();
			d.width = COLUMN_WIDTH;
			temp.setPreferredSize(d);
			temp.setMaximumSize(d);
			temp.setMinimumSize(d);
			
			row.add(temp);
		}		
		return row;
	}
	
	private void createSelections() {
		selections = new JRadioButton[theLibraryNames.length][];
		for(int x=0; x<theLibraryNames.length; x++) {
			selections[x] = new JRadioButton[SELECTIONS.length-1];
			ButtonGroup grp = new ButtonGroup();
			for(int y=0; y<selections[x].length; y++) {
				selections[x][y] = new JRadioButton();
				selections[x][y].setBackground(Color.WHITE);
				selections[x][y].setAlignmentX(Component.CENTER_ALIGNMENT);
				selections[x][y].setMaximumSize(selections[x][y].getPreferredSize());
				selections[x][y].setMinimumSize(selections[x][y].getPreferredSize());
				
				grp.add(selections[x][y]);
			}
		}
		for(int x=0; x<theLibraryNames.length; x++) {
			mainPanel.add(createRow(x));
		}
	}

	private JPanel getModePanel() {
		JPanel retVal = new JPanel();
		retVal.setLayout(new BoxLayout(retVal, BoxLayout.PAGE_AXIS));
		retVal.setAlignmentX(Component.LEFT_ALIGNMENT);
		retVal.setBackground(Color.WHITE);
		retVal.add(new JLabel("Method: "));
				
		modes = new JRadioButton[QRProcess.METHOD_NAMES.length];
		minors = new Vector<Vector<JRadioButton>> ();
		
		ButtonGroup grpMethod = new ButtonGroup();

		//minor method data
		minors.add(new Vector<JRadioButton> ());
		ButtonGroup edgeRMinorGroup = new ButtonGroup();
		for(int x=0; x<QRProcess.EDGER_MINOR_NAMES.length; x++) {
			minors.get(minors.size() - 1).add(new JRadioButton(QRProcess.EDGER_MINOR_NAMES[x]));
			minors.get(minors.size() - 1).get(x).setBackground(Color.WHITE);
			minors.get(minors.size() - 1).get(x).setSelected(x == 0);
			edgeRMinorGroup.add(minors.get(minors.size() -1).get(x));
		}
		
		minors.add(new Vector<JRadioButton> ());
		ButtonGroup degSEQMinorGroup = new ButtonGroup();
		for(int x=0; x<QRProcess.DEGSEQ_MINOR_NAMES.length; x++) {
			minors.get(minors.size() - 1).add(new JRadioButton(QRProcess.DEGSEQ_MINOR_NAMES[x]));
			minors.get(minors.size() - 1).get(x).setBackground(Color.WHITE);
			minors.get(minors.size() - 1).get(x).setSelected(x == 0);
			degSEQMinorGroup.add(minors.get(minors.size() -1).get(x));
		}
		
		minors.add(new Vector<JRadioButton> ());
		ButtonGroup baySEQMinorGroup = new ButtonGroup();
		for(int x=0; x<QRProcess.BAYSEQ_MINOR_NAMES.length; x++) {
			minors.get(minors.size() - 1).add(new JRadioButton(QRProcess.BAYSEQ_MINOR_NAMES[x]));
			minors.get(minors.size() - 1).get(x).setBackground(Color.WHITE);
			minors.get(minors.size() - 1).get(x).setSelected(x == 0);
			baySEQMinorGroup.add(minors.get(minors.size() -1).get(x));
		}
		
		for(int x=0; x<modes.length; x++) {
			modes[x] = new JRadioButton(QRProcess.METHOD_NAMES[x]);
			modes[x].setAlignmentX(Component.LEFT_ALIGNMENT);
			grpMethod.add(modes[x]);
			modes[x].setBackground(Color.WHITE);
			modes[x].addActionListener(new ActionListener() 
			{
				public void actionPerformed(ActionEvent arg0) 
				{
					int modeID = 0;
					for(int x=0;  x<modes.length; x++) {
						if(modes[x].isSelected()) {
							String selection = modes[x].getText();
							modeID = getIDNum(selection, QRProcess.METHOD_NAMES, QRProcess.METHOD_IDS);
						}
					}
					if (modeID == QRProcess.METHOD_EDGER || modeID == QRProcess.METHOD_DESEQ)
					{
						chkDisp.setEnabled(true);
						lblDisp.setEnabled(true);
						txtDisp.setEnabled(true);
					}
					else
					{
						chkDisp.setEnabled(false);
						lblDisp.setEnabled(false);
						txtDisp.setEnabled(false);						
					}
					
				}
			});
		}
		
		retVal.add(Box.createVerticalStrut(5));
		for(int x=0; x<modes.length; x++) {
			JPanel row = new JPanel();
			row.setLayout(new BoxLayout(row, BoxLayout.LINE_AXIS));
			row.setAlignmentX(Component.LEFT_ALIGNMENT);
			row.setBackground(Color.WHITE);
			row.add(Box.createHorizontalStrut(10));
			row.add(modes[x]);
			if(minors.get(x).size() > 0) {
				row.add(new JLabel(":"));
				for(int y=0; y<minors.get(x).size(); y++) {
					row.add(Box.createHorizontalStrut(10));
					row.add(minors.get(x).get(y));
				}
			}
			retVal.add(row);
		}
		modes[0].setSelected(true);
		retVal.setMaximumSize(retVal.getPreferredSize());
		retVal.setMinimumSize(retVal.getPreferredSize());
		return retVal;
	}
	private void runGOSeq() {
		boolean usePercent = btnPercent.isSelected();
		String strThresh = (usePercent ? txtPercent.getText() : txtPVal.getText());
		double thresh = Double.parseDouble(strThresh);
		String selected = cmbPvalColumns.getSelectedItem();
		boolean all = selected.equals(allCols);
		String [] cols = cmbPvalColumns.getColumns(); // CAS 1/25/13
		for (int i=0; i<cols.length; i++) {
			if (!cols[i].equals(allCols) && !cols[i].equals(selCol))
				cols[i] = pValColPrefix + cols[i];
		}
		qrProcess.runGOSeq(cols,pValColPrefix + cmbPvalColumns.getSelectedItem(),
				all,usePercent,thresh);
	}
	private void updateColumnList() {
		cmbPvalColumns.removeAllItems();
		cmbPvalColumns.addItem(selCol);
		String [] vals = getColumnList();
		for(int x=0; x<vals.length; x++) 
			vals[x] = vals[x].substring(2); // CAS remove P_
		if(vals.length > 1)					// changed 2 to 1
			cmbPvalColumns.addItem(allCols);
		
		for(int x=0; x<vals.length; x++)
			cmbPvalColumns.addItem(vals[x]);
		cmbPvalColumns.setMaximumSize(cmbPvalColumns.getPreferredSize());
		cmbPvalColumns.setMinimumSize(cmbPvalColumns.getPreferredSize());
		cmbPvalColumns.setEnabled(cmbPvalColumns.getItemCount() > 1);
		cmbPvalColumns.setSelectedIndex(0);
		btnRemoveColumns.setEnabled(false);
		btnGOSeq.setEnabled(false);
	}
	private JPanel createRemovePanel() {
		JPanel retVal = getRowPanel();
		lblRemoveColumns  = new JLabel(""); 
		lblRemoveColumns.setEnabled(false);
		cmbPvalColumns = new ButtonComboBox();
		cmbPvalColumns.setEnabled(false);
		cmbPvalColumns.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				if(cmbPvalColumns.getSelectedIndex() == 0 ) {
					btnRemoveColumns.setEnabled(false);
					btnGOSeq.setEnabled(false);
					lblRemoveColumns.setEnabled(false);
				}
				else {
					btnRemoveColumns.setEnabled(true);
					btnGOSeq.setEnabled(true);
					lblRemoveColumns.setEnabled(true);
				}
			}
		});
		btnRemoveColumns = new JButton("Remove");
		btnRemoveColumns.setBackground(ManagerFrame.BGCOLOR);
		btnRemoveColumns.setEnabled(false);
		btnRemoveColumns.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				try {
					if(cmbPvalColumns.getSelectedIndex() > 0) {
						String column = (String)cmbPvalColumns.getSelectedItem();
						if (!column.equals(allCols)) {
							removeColumn(column);
							updateColumnList();
						}
						else {
							int nItems = cmbPvalColumns.getItemCount();
							Vector<String> columns = new Vector<String>();
							for (int i = 0; i < nItems; i++)
							{
								column = cmbPvalColumns.getItemAt(i);
								if (!column.equals(allCols) && !column.equals(selCol)) {
									columns.add(column);
								}
							}
							for (String name :columns)
							{
								removeColumn(name);
								updateColumnList();								
							}
						}
						System.out.println("Completed removal ");
					}
				}
				catch(Exception e) {
					ErrorReport.prtReport(e, "Error removing method column");
				}
			}
		});
		
		retVal.add(lblRemoveColumns);
		retVal.add(cmbPvalColumns);
		retVal.add(Box.createHorizontalStrut(10));
		retVal.add(btnRemoveColumns);
			
		return retVal;
	}
	private JPanel createGOPanel() {
		JPanel retVal = getRowPanel();
		
		btnGOSeq = new JButton("Execute GOseq");
		btnGOSeq.setEnabled(false);
		btnGOSeq.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				runGOSeq();
			}
		});
		
		ButtonGroup group = new ButtonGroup();
		btnPercent = new JRadioButton("Top");
		btnPercent.setBackground(Color.WHITE);
		btnPVal = new JRadioButton("Pval");
		btnPVal.setBackground(Color.WHITE);
		
		group.add(btnPercent);
		group.add(btnPVal);
		
		btnPVal.setSelected(true);
		
		txtPercent = new JTextField(3);
		txtPercent.setMaximumSize(txtPercent.getPreferredSize());
		txtPercent.setMinimumSize(txtPercent.getPreferredSize());
		txtPercent.setText(defPercent);
		
		txtPVal = new JTextField(5);
		txtPVal.setMaximumSize(txtPercent.getPreferredSize());
		txtPVal.setMinimumSize(txtPercent.getPreferredSize());
		txtPVal.setText(defPVal);
		
		retVal.add(btnGOSeq);
		retVal.add(Box.createHorizontalStrut(5));
		retVal.add(btnPercent);
		retVal.add(Box.createHorizontalStrut(5));
		retVal.add(txtPercent);
		retVal.add(new JLabel("%"));
		retVal.add(Box.createHorizontalStrut(5));
		retVal.add(new JLabel("or"));
		retVal.add(Box.createHorizontalStrut(5));
		retVal.add(btnPVal);
		retVal.add(Box.createHorizontalStrut(5));
		retVal.add(txtPVal);
		
		return retVal;
	}
	private JPanel createRow(int rowNum) {
		JPanel retVal = getRowPanel();
		
		JPanel temp = getRowPanel();
		temp.add(rowHeaders[rowNum]);
		Dimension d = temp.getPreferredSize();
		d.width = COLUMN_WIDTH;
		temp.setPreferredSize(d);
		temp.setMaximumSize(d);
		temp.setMinimumSize(d);
		retVal.add(temp);
		
		for(int x=0; x<selections[rowNum].length; x++) {
			temp = getRowPanel();
			if(x == DEFAULT_SELECTION)
				selections[rowNum][x].setSelected(true);
			else
				selections[rowNum][x].setSelected(false);
			
			temp.add(selections[rowNum][x]);
			d = temp.getPreferredSize();
			d.width = COLUMN_WIDTH;
			temp.setPreferredSize(d);
			temp.setMaximumSize(d);
			temp.setMinimumSize(d);
			retVal.add(temp);
		}
		return retVal;
	}
	
	public boolean isSelectedAt(int x, int y) { return selections[x][y].isSelected(); }
	
	private void createRowHeaders(String [] headers) {
		int maxWidth = 0;
		rowHeaders = new JLabel[headers.length];
		for(int x=0; x<headers.length; x++) {
			rowHeaders[x] = new JLabel(headers[x]);
			if(rowHeaders[x].getPreferredSize().width > maxWidth)
				maxWidth = rowHeaders[x].getPreferredSize().width;
		}
		
		for(int x=0; x<rowHeaders.length; x++) {
			Dimension d = rowHeaders[x].getPreferredSize();
			d.width = maxWidth;
			rowHeaders[x].setPreferredSize(d);
			rowHeaders[x].setMaximumSize(d);
			rowHeaders[x].setMinimumSize(d);
		}
	}
	private JPanel createFDRPanel()
	{
		JPanel retVal = new JPanel();
		retVal.setLayout(new BoxLayout(retVal, BoxLayout.LINE_AXIS));
		retVal.setAlignmentX(Component.LEFT_ALIGNMENT);
		retVal.setBackground(Color.WHITE);
	
		btnFDR = new JCheckBox();
		btnFDR.setBackground(Color.white);
		retVal.add(btnFDR);
		retVal.add(Box.createHorizontalStrut(5));
		lblFDR = new JLabel("Convert p-values to False Discovery Rate");
		retVal.add(lblFDR);
		lblFDR.setEnabled(true);
		btnFDR.setSelected(true);

		btnFDR.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent arg0) 
			{
				if (btnFDR.isSelected())
				{
					lblFDR.setEnabled(true);
				}
				else
				{
					lblFDR.setEnabled(false);
				}
			}
		});
		
		return retVal;
	}
	private JPanel createNormPanel()
	{
		norms = new Vector<JRadioButton> ();
		ButtonGroup bg = new ButtonGroup();
		
		JPanel retVal = new JPanel();
		retVal.setLayout(new BoxLayout(retVal, BoxLayout.LINE_AXIS));
		retVal.setAlignmentX(Component.LEFT_ALIGNMENT);
		retVal.setBackground(Color.WHITE);	
		retVal.add(new JLabel("Normalization:"));
		retVal.add(Box.createHorizontalStrut(10));

		for(int x=0; x<QRProcess.NORM_NAMES.length; x++) 
		{
			JRadioButton btn = new JRadioButton(QRProcess.NORM_NAMES[x]);
			btn.setBackground(Color.WHITE);
			btn.setSelected(x == 0);
			retVal.add(btn);
			norms.add(btn);
			bg.add(btn);
			retVal.add(Box.createHorizontalStrut(10));
		}
		return retVal;
	}
	private JPanel createDispPanel()
	{
		JPanel retVal = new JPanel();
		retVal.setLayout(new BoxLayout(retVal, BoxLayout.LINE_AXIS));
		retVal.setAlignmentX(Component.LEFT_ALIGNMENT);
		retVal.setBackground(Color.WHITE);
		
		chkDisp = new JCheckBox();
		chkDisp.setBackground(Color.WHITE);
		chkDisp.setSelected(false);
		retVal.add(chkDisp);
		retVal.add(Box.createHorizontalStrut(5));
		
		lblDisp = new JLabel("Use fixed dispersion:");
		retVal.add(lblDisp);
		retVal.add(Box.createHorizontalStrut(5));
		txtDisp = new JTextField(10);
		txtDisp.setText(String.valueOf(QRProcess.dispersion));
		txtDisp.setMaximumSize(txtDisp.getPreferredSize());
		retVal.add(txtDisp);
		
		return retVal;
	}
	private JPanel createDBPanel()
	{
		JPanel retVal = new JPanel();
		retVal.setLayout(new BoxLayout(retVal, BoxLayout.LINE_AXIS));
		retVal.setAlignmentX(Component.LEFT_ALIGNMENT);
		retVal.setBackground(Color.WHITE);
	
		btnAddCol = new JCheckBox();
		btnAddCol.setBackground(Color.white);
		retVal.add(btnAddCol);
		retVal.add(Box.createHorizontalStrut(5));
		lblAdd = new JLabel("Save results in Pval column:");
		retVal.add(lblAdd);
		retVal.add(Box.createHorizontalStrut(5));
		txtColName = new JTextField(10);
		txtColName.setMaximumSize(txtColName.getPreferredSize());
		retVal.add(Box.createHorizontalStrut(5));
		lblAdd2 = new JLabel("(up to 10 chars, using letters, numbers, and underscores)");
		txtColName.setEnabled(false);
		lblAdd.setEnabled(true);
		lblAdd2.setEnabled(false);
		
		retVal.add(txtColName);

		btnAddCol.addActionListener(new ActionListener() 
		{
			public void actionPerformed(ActionEvent arg0) 
			{
				if (btnAddCol.isSelected())
				{
					txtColName.setEnabled(true);
					lblAdd.setEnabled(true);
					lblAdd2.setEnabled(true);
					TreeSet<String> grp1 = new TreeSet <String> ();
					TreeSet<String> grp2 = new TreeSet <String> ();		
					for(int x=0; x<theLibraryNames.length; x++) 
					{
						if (isSelectedAt(x, 0)) grp1.add(theLibraryNames[x]);
						else if (isSelectedAt(x, 1)) grp2.add(theLibraryNames[x]);
					}
					if (grp1.size() != 0 && grp2.size() != 0) {
						String cname="";
						cname = colNameCreate(grp1, grp2, cname);
						if (cname != null) txtColName.setText(cname);
					}	
				}
				else
				{
					txtColName.setEnabled(false);
					lblAdd.setEnabled(false);
					lblAdd2.setEnabled(false);
				}
			}
		});
		retVal.setMaximumSize(retVal.getPreferredSize());
		retVal.setMinimumSize(retVal.getPreferredSize());
		
		return retVal;
	}
	
	private int getIDNum(String val, String [] values, int [] ids) {
		for(int x=0; x<values.length; x++)
			if(val.equals(values[x]))
				return ids[x];
		System.err.println("getIDNum for bad value " + val);
		System.exit(-1);
		return -1;
	}
	/*************************************************
	 * XXX row starting with Execute
	 */
	private JPanel createExecutePanel() {
		JPanel retVal = getRowPanel();
		
		btnExecute = new JButton("Execute");
		btnExecute.addActionListener(new ActionListener()  {
			public void actionPerformed(ActionEvent arg0) {
				getMethodsFromPanel();
				doExecute(modeID, normID, minorID, txtColName.getText(), disp);
				updateColumnList();
			}
		});		
		retVal.add(btnExecute);
		retVal.add(Box.createHorizontalStrut(10));

		btnExecuteAll = new JButton("All Pairs for Group 1");
		btnExecuteAll.addActionListener(new ActionListener()  {
			public void actionPerformed(ActionEvent arg0) {
				getMethodsFromPanel();
				doExecuteAll(modeID, normID, minorID, disp);
				updateColumnList();
			}
		});
		retVal.add(btnExecuteAll);
		retVal.add(Box.createHorizontalStrut(10));
		
		btnExecuteFile = new JButton("Get Pairs from File");
		btnExecuteFile.addActionListener(new ActionListener()  {
			public void actionPerformed(ActionEvent arg0) {
				String fname = fileChooser();
				if (fname != null) {
					getMethodsFromPanel();
					doExecuteFile(modeID, normID, minorID, disp, fname);
					updateColumnList();
				}
			}
		});
		retVal.add(btnExecuteFile);
		retVal.add(Box.createHorizontalStrut(10));
		
		final JButton btnHelp = new JButton("Help");
	       btnHelp.setBackground(ManagerFrame.HELPCOLOR);
	       btnHelp.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				UserPrompt.displayHTMLResourceHelp(getInstance(), "RunDE Help", "html/runDE/QRFrame.html");
			}
	       });
	    retVal.add(btnHelp);
		return retVal;
	}
	// this is used by the three types of execute
	private int modeID = -1, normID = -1, minorID = -1;
	private double disp = -1;
	private void getMethodsFromPanel() {
		String selection = "";
		int selPos = 0;
		
		for(int x=0; selection.length() == 0 && x<modes.length; x++) {
			if(modes[x].isSelected()) {
				selPos = x;
				selection = modes[x].getText();
			}
		}		
		modeID = getIDNum(selection, QRProcess.METHOD_NAMES, QRProcess.METHOD_IDS);
		
		for(int x=0;  x<norms.size(); x++) {
			if(norms.get(x).isSelected()) {
				selection = norms.get(x).getText();
			}
		}		
		normID = getIDNum(selection, QRProcess.NORM_NAMES, QRProcess.NORM_IDS);
		
		String minorSel = "";
		switch(modeID) {
		case QRProcess.METHOD_EDGER:
			for(int x=0; x<minors.get(selPos).size(); x++) {
				if(minors.get(selPos).get(x).isSelected()) {
					minorSel = minors.get(selPos).get(x).getText();
				}
				minorID = getIDNum(minorSel, QRProcess.EDGER_MINOR_NAMES, QRProcess.EDGER_MINOR_IDS);
			}
			break;
		case QRProcess.METHOD_DEGSEQ:
			for(int x=0; x<minors.get(selPos).size(); x++) {
				if(minors.get(selPos).get(x).isSelected()) {
					minorSel = minors.get(selPos).get(x).getText();
				}
				minorID = getIDNum(minorSel, QRProcess.DEGSEQ_MINOR_NAMES, QRProcess.DEGSEQ_MINOR_IDS);
			}
			break;
		case QRProcess.METHOD_BAYSEQ:
			for(int x=0; x<minors.get(selPos).size(); x++) {
				if(minors.get(selPos).get(x).isSelected()) {
					minorSel = minors.get(selPos).get(x).getText();
				}
				minorID = getIDNum(minorSel, QRProcess.BAYSEQ_MINOR_NAMES, QRProcess.BAYSEQ_MINOR_IDS);
			}
			break;
		case QRProcess.METHOD_DESEQ:
			for(int x=0; x<minors.get(selPos).size(); x++) {
				if(minors.get(selPos).get(x).isSelected()) {
					minorSel = minors.get(selPos).get(x).getText();
				}
				minorID = getIDNum(minorSel, QRProcess.DESEQ_MINOR_NAMES, QRProcess.DESEQ_MINOR_IDS);
			}
			break;

		}
		if (modeID == QRProcess.METHOD_DESEQ || modeID == QRProcess.METHOD_EDGER)
		{
			if (chkDisp.isSelected())
			{
				try
				{
					disp = Double.parseDouble(txtDisp.getText());
				}
				catch(Exception e)
				{
					System.err.println("Invalid dispersion:" + txtDisp.getText());
					return;
				}
			}
		}
	}
	private JPanel getRowPanel() {
		JPanel retVal = new JPanel();
		retVal.setLayout(new BoxLayout(retVal, BoxLayout.LINE_AXIS));
		retVal.setBackground(Color.WHITE);
		retVal.setAlignmentX(Component.LEFT_ALIGNMENT);	
		return retVal;
	}
	// XXX Get file name for file of group1, group2, colname
	private String fileChooser() {
		try {
			final JFileChooser fc = new JFileChooser();
			String current = new java.io.File( "." ).getCanonicalPath();
			String start = current + "/projects";
			fc.setCurrentDirectory(new File(start));
			if(fc.showOpenDialog(parent) == JFileChooser.APPROVE_OPTION) {
				return fc.getSelectedFile().getAbsolutePath();
			}
		}
		catch (Exception e) {
			ErrorReport.reportError(e, "Problems getting file");
		}
		return null;
	}
	/******************************************************
	 * PAVEdb chooser methods
	 */
	private JPanel createAssemblySelectionPanel(Vector<SessionData> inAssemblyList) 
	{
	       JPanel selectAssemblyPanel = new JPanel();

	       selectAssemblyPanel.setBackground(Color.WHITE);

	       // Create a tree of the hosts
	       DefaultMutableTreeNode hostTree = new DefaultMutableTreeNode("");
	       DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(hosts.host);
		   hostTree.add(newNode);
		   DefaultMutableTreeNode start = newNode;

	       // Add assembly nodes to host nodes
	       // The session only has a list of assemblies
	       // Create tree sorted on hosts, then paveDB names
	       // This is inefficient, but not enough items to matter
	       // Somewhere, theSession.toString is called for the [...] description on the PAVE assemblies
	       for (int i = 0; i < hostTree.getChildCount(); i++) {
	           DefaultMutableTreeNode hostNode = (DefaultMutableTreeNode) hostTree.getChildAt(i);
	           
               for (SessionData theSession : inAssemblyList) {
                   AssemblyData ad = theSession.getAssembly(0);
                   String hostName = ad.getDBData().getDB_URL();
                                   
                   if (hostName.equals(hostNode.toString()))
                   {
                       hostNode.add(new DefaultMutableTreeNode(theSession));
                   }
               } 
	       }

	       // Create display tree
	       DefaultTreeModel assemblyModel = new DefaultTreeModel(hostTree);
	       final JTree assemblyTree = new JTree(assemblyModel);
	       assemblyTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
	       assemblyTree.setRootVisible(false);
	       assemblyTree.setToggleClickCount(1);
	       ((DefaultTreeCellRenderer) assemblyTree.getCellRenderer()).setLeafIcon(null);
	       if (assemblyTree.getRowCount() == 1)
	           assemblyTree.expandRow(0);

	       assemblyTree.addMouseListener(new MouseAdapter() {
	           public void mouseClicked(MouseEvent e) {
	        	   try {
		               TreePath path = assemblyTree.getSelectionPath();
		               if (path != null) {
		                   int depth = path.getPathCount();
		                   if (e.getClickCount() == 2 && depth >= 3) {
		                       DefaultMutableTreeNode node =
		                           (DefaultMutableTreeNode) assemblyTree
		                               .getLastSelectedPathComponent();
				               new QRFrame(getSettings(), getSessionString((SessionData) node.getUserObject()));
		                   }
		               }
	        	   }
	        	   catch(Exception ex) {
	        		   ErrorReport.prtReport(ex, "Error launching DE window");
	        	   }
	           }
	       });

	       final JScrollPane assemblyScrollPane = new JScrollPane(assemblyTree);
	       assemblyScrollPane.setPreferredSize(new Dimension(400, 400));
	       Dimension dim = assemblyScrollPane.getMaximumSize();
	       assemblyScrollPane.setMaximumSize(new Dimension(Math.max(400,
	               (int) dim.getWidth()), Math.max(400, (int) dim.getHeight())));
	       assemblyScrollPane.setAlignmentX(Component.CENTER_ALIGNMENT);

	       final JButton btnViewAssembly = new JButton("Launch");
	       btnViewAssembly.setAlignmentX(Component.CENTER_ALIGNMENT);
	       btnViewAssembly.setBackground(ManagerFrame.LAUNCHCOLOR);
	       btnViewAssembly.setEnabled(false);

	       btnViewAssembly.addActionListener(new ActionListener() {
	           public void actionPerformed(ActionEvent event) {
	        	   try {
		               DefaultMutableTreeNode node = (DefaultMutableTreeNode)
		                   assemblyTree.getLastSelectedPathComponent();
		               new QRFrame(getSettings(), getSessionString((SessionData) node.getUserObject()));
	        	   }
	        	   catch(Exception e) {
	        		   ErrorReport.prtReport(e, "Error launching DE window");
	        	   }
	           }
	       });
	       
			final JButton btnGetState = new JButton("Overview");
			btnGetState.setBackground(ManagerFrame.LAUNCHCOLOR);
			btnGetState.setAlignmentX(Component.LEFT_ALIGNMENT);
			btnGetState.setEnabled(false);
			btnGetState.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent arg0) {
					try {
						String val = null;
						
						paveDBs = getSettings();
						DefaultMutableTreeNode node = (DefaultMutableTreeNode) assemblyTree.getLastSelectedPathComponent();
						String dbName = setConnection(getSessionString((SessionData) node.getUserObject()));
						if(dbName != null) {
							ResultSet rset = st.executeQuery("SELECT pja_msg FROM assem_msg");
							
							if(rset.first()) {
								val = rset.getString(1);
								if (val==null || (val != null && val.length() <= 10)) {
									OverviewDBWrapper ov = new OverviewDBWrapper(conn);
									Vector <String> lines = new Vector <String> ();
									val = ov.createOverview(lines);
								}
							}
							rset.close();
						}
						UserPrompt.displayInfoMonoSpace(getInstance(), "Overview for " + dbName, 
								val.split("\n"), false, true);
					}
					catch(Exception e) {
						ErrorReport.prtReport(e, "Error getting project state");
					}
				}
			});

			final JButton btnClose = new JButton("Exit");
		       btnClose.setBackground(Color.WHITE);
		       btnClose.addActionListener(new ActionListener() {
		    	   public void actionPerformed(ActionEvent arg0) {
		    		   dispose();
		    	   }
		       });
		       
	       final JButton btnCloseAll = new JButton("Exit All");
	       btnCloseAll.setBackground(Color.WHITE);
	       btnCloseAll.addActionListener(new ActionListener() {

	    	   public void actionPerformed(ActionEvent arg0) {
	    		   if(openWindows != null) {
	    			   for(int x=0; x<openWindows.size(); x++) {
	    				   openWindows.get(x).dispose();
	    			   }
	    			   openWindows.removeAllElements();
	    		   }
	    		   dispose();
	    	   }
	       });      
	       	       
	       assemblyTree.addTreeSelectionListener(new TreeSelectionListener() {
	           public void valueChanged(TreeSelectionEvent e) {
	               int depth = assemblyTree.getSelectionPath().getPathCount();
	               btnViewAssembly.setEnabled(depth >= 3);
	               btnGetState.setEnabled(depth >= 3);
	           }
	       });

	       // Select current host in list
	       if (start != null) {
	           TreeNode[] nodes = assemblyModel.getPathToRoot(start.getFirstLeaf());
	           TreePath path = new TreePath(nodes);
	           assemblyTree.scrollPathToVisible(path);
	           assemblyTree.setSelectionPath(path);
	       }

	       JPanel buttonPanel = new JPanel();
	       buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.LINE_AXIS));
	       buttonPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
	       buttonPanel.setBackground(Color.WHITE);
	       buttonPanel.add(btnViewAssembly);
	       buttonPanel.add(Box.createHorizontalStrut(10));
	       buttonPanel.add(btnGetState);
	       buttonPanel.add(Box.createHorizontalStrut(10));
	       buttonPanel.add(btnClose);
	       buttonPanel.add(Box.createHorizontalStrut(10));
	       buttonPanel.add(btnCloseAll);
	       
	       buttonPanel.setMaximumSize(buttonPanel.getPreferredSize());
	       buttonPanel.setMinimumSize(buttonPanel.getPreferredSize());
	       
	       selectAssemblyPanel.setLayout(new BoxLayout(selectAssemblyPanel,
	               BoxLayout.Y_AXIS));
	       selectAssemblyPanel.add(Box.createVerticalStrut(20));
	       selectAssemblyPanel.add(UIHelpers.createCenteredLabel("singleTCW Databases"));
	       selectAssemblyPanel.add(assemblyScrollPane);
	       selectAssemblyPanel.add(Box.createVerticalStrut(5));
	       selectAssemblyPanel.add(buttonPanel);
	       selectAssemblyPanel.add(Box.createVerticalStrut(20));
	       selectAssemblyPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));

	       return selectAssemblyPanel;
	}
	
	private QRFrame getInstance() { return this; }
	
	private static String getSessionString(SessionData sData) {
		String retVal = "";
		
		retVal = sData.getAssembly(0).getAssemblyID() + ":" + 
				sData.getAssembly(0).getDBData().getDBName() + ":" + 
				sData.getAssembly(0).getDBData().getDB_URL();
		return retVal;
	}
	/************************************************************
	 * Database methods
	 */
	private String setConnection(String options) {
		String assemblyID = null;
		String hostName = null;
		String dbName = null;
		
		HostsCfg hosts = new HostsCfg();
		
		if(options == null) ErrorReport.die("Should not have null options");
		
		String[] tokens = options.split(":"); // check for 3 args in QRmain
		assemblyID = tokens[0];
		hostName = hosts.host; 
		dbName = tokens[1];
		
		strTitle = assemblyID + " "  + dbName + " on " + hostName;
		if(dbName != null)
			System.err.println("Open " + strTitle);
		
		// Find session with specified assembly
		selectedDB = null;
		Vector<SessionData> sessions = 
				SessionData.getAssemblySessions(paveDBs.getAllSessions());
		for (SessionData session : sessions) {
			AssemblyData assembly = session.getAssembly(0);
			if (assembly == null) break;
			DatabaseData db = assembly.getDBData();
			if (db == null) break;

			if ( (dbName == null || db.getDBName().equals(dbName))
					&& (assembly.getAssemblyID().equals(assemblyID)) ) 
			{
				selectedDB = session;
				break;
			}
		}

		if(selectedDB != null) {
			try {
				AssemblyData assmData = selectedDB.getAssembly(0);
				DatabaseData dbData = assmData.getDBData();		
				conn = dbData.createDBConnection();
				st = conn.createStatement();			
				theLibraryNames = loadLibraryNames();
			}
			catch(Exception e) {
				ErrorReport.prtReport(e, "Error getting databse information");
				return null;
			}
		}
		else {
			ErrorReport.die("Error: Could not find assembly: " + options);
			return null;
		}
		return dbName;
	}
	
	private String [] loadLibraryNames() {
		try {
			AssemblyData assmData = selectedDB.getAssembly(0);
			DatabaseData dbData = assmData.getDBData();		
			Connection conn = dbData.createDBConnection();
			Statement stmt = conn.createStatement();
			
			Vector<String> names = new Vector<String> ();
			ResultSet rset = stmt.executeQuery("SELECT libid FROM library where ctglib=0");
			while(rset.next()) {
				names.add(rset.getString(1));
			}			
			return names.toArray(new String[0]);
		}
		catch(Exception e) {
			ErrorReport.prtReport(e, "Error loading data");
		}		
		return null;
	}
	
	public void removeColumn(String column) {
		try {
			Statement stmt = conn.createStatement();
	
			System.out.println("Removing column " + column + " (may take a while)...");
			column =  pValColPrefix + column;
			stmt.executeUpdate("ALTER TABLE contig DROP COLUMN " + column);
			
			// CAS 12/28/14 add
			ResultSet rs = stmt.executeQuery("show tables like 'libraryDE'");
			if (rs.first()) {
				rs = stmt.executeQuery("select title from libraryDE where pCol='" + column + "'");
				if (rs.first()) {
					stmt.executeUpdate("delete from libraryDE where pCol='" + column + "'");
				}
			}
			
			try { // try since column might not exist
				stmt.executeUpdate("alter table go_info drop column " + column);
			}
			catch(Exception e){}
			stmt.executeUpdate("update assem_msg set pja_msg=NULL"); 
		}
		catch(Exception e) {
			ErrorReport.prtReport(e, "Error removing column");
		}
	}
	
	public String [] getColumnList() {
		Vector<String> names = new Vector<String> ();
		try {
			Statement stmt = conn.createStatement();
			ResultSet rset = stmt.executeQuery("SHOW COLUMNS FROM contig");
			while(rset.next()) {
				String row = rset.getString(1);
				if(row.startsWith("P_"))
					names.add(row);
			}
		}
		catch (Exception e){
			ErrorReport.prtReport(e, "Error getting method columns");
		}
		
		return names.toArray(new String[0]);
	}
	
	boolean columnExists(String tbl, String cname) throws Exception
	{
		boolean ret = false;
		ResultSet rs = st.executeQuery("show columns from " + tbl + " where field='" + cname + "'");
		if (rs.first()) ret = true;
		rs.close();
		return ret;	
	}
	
	//Window event code
	public void windowClosed(WindowEvent arg0) {
		if(openWindows != null)
			openWindows.remove(this); 
	}
	public void windowActivated(WindowEvent arg0) {}
	public void windowClosing(WindowEvent arg0) {}
	public void windowDeactivated(WindowEvent arg0) {}
	public void windowDeiconified(WindowEvent arg0) {}
	public void windowIconified(WindowEvent arg0) {}
	public void windowOpened(WindowEvent arg0) {}
	
	public GlobalSettings getSettings() { return paveDBs; }
	/***************************************************************
	 * Object variables
	 */
	private JPanel mainPanel = null;
	private JLabel [] rowHeaders = null;
	private JLabel [] colHeaders = null;
	private JRadioButton [][] selections = null;
	private JRadioButton [] modes = null;
	private Vector<JRadioButton> norms = null;
	private Vector<Vector<JRadioButton>> minors = null;
	private JButton btnExecute = null;
	private JButton btnExecuteAll = null;
	private JButton btnExecuteFile = null;
	
	private JLabel lblRemoveColumns = null;
	private ButtonComboBox cmbPvalColumns = null;
	private JButton btnRemoveColumns = null;
	private JButton btnGOSeq = null;
	
	private JRadioButton btnPercent = null;
	private JRadioButton btnPVal = null;
	
	private JTextField txtPercent = null;
	private JTextField txtPVal = null;
	
	private QRProcess qrProcess = null;
		
	private JCheckBox btnAddCol, btnFDR, chkDisp;
	private JTextField txtColName;
	private JTextField txtDisp;
	private JLabel lblAdd, lblAdd2, lblFDR, lblDisp;

	private GlobalSettings paveDBs = null;
	private SessionData selectedDB = null; 
	private String [] theLibraryNames = null;
	private String strTitle = null;
	private QRFrame parent=null;

	private Statement st;
	private Connection conn;
}
